Advanced data visualization with R and ggplot2



This practical follows the previous basic introduction to ggplot2. It allows to go further with ggplot2: how to annotate a chart, how to build interactive charts, how to customize colors, and more.

Get ready


The following libraries are needed all along the practical. Install them with install.packages() if you do not have them already. Then load them with library().

# Load it
library(ggplot2)
library(dplyr)
library(hrbrthemes)
library(viridis)

1- General appearance


→ Titles


Q1.1 - The code below builds a basic histogram for values under 300. Add code to:

  • add a title with ggtitle()
  • change axis labels xlab() and ylab()
  • change axis limits with xlim() and ylim()
# Libraries
library(ggplot2)

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/1_OneNum.csv", header=TRUE)

# Make the histogram
data %>%
  filter( price<300 ) %>%
  ggplot( aes(x=price)) +
    geom_histogram() +
    ggtitle("Night price distribution of Airbnb appartements") +
    xlab("Night price") +
    ylab("Number of apartments") +
    xlim(0,400)

# Libraries
library(tidyverse)
library(hrbrthemes)
library(viridis)

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/1_OneNum.csv", header=TRUE)

# Make the histogram
data %>%
  filter( price<300 ) %>%
  ggplot( aes(x=price)) +
    stat_bin(breaks=seq(0,300,10), fill="#69b3a2", color="#e9ecef", alpha=0.9) +
    ggtitle("Night price distribution of Airbnb appartements") +
    theme_ipsum()

1- Annotation


Annotation is a crucial component of a good dataviz. It can turn a boring graphic into an interesting and insightful way to convey information. Dataviz is often separated in two main types: exploratory and explanatory analysis. Annotation is used for the second type.

→ Text

The most common type of annotation is text. Let’s say you have a spike in a line plot. It totally makes sense to highlight it, and explain more in details what it is about.


Q1.1 - Build a line plot showing the bitcoin price evolution between 2013 and 2018. Dataset is located here and can be read directly with read.table(). What part of the chart would you highlight?

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered.csv", header=T)
data$date <- as.Date(data$date)

# plot
data %>%
  ggplot( aes(x=date, y=value)) +
    geom_line(color="#69b3a2")


Q1.2 - Use the annotate() function to add text. Annotate requires several arguments:

  • geom: type of annotation, use text
  • x: position on the X axis
  • y: position on the Y axis
  • label: what you want to write
  • Optional: color, size, angle and more.
# plot
data %>%
  ggplot( aes(x=date, y=value)) +
    geom_line(color="#69b3a2") +
    annotate(geom="text", x=as.Date("2017-01-01"), y=19000, 
             label="Bitcoin price reached 20k $\nat the end of 2017")

→ Shape


Q1.3 - To highlight the spike even more, draw a circle around it. Note that you first need to find the exact spike date and its value

# Find spike date and value:
# data %>% arrange(desc(value)) %>% head(1)

# plot
data %>% 
  ggplot( aes(x=date, y=value)) +
    geom_line(color="#69b3a2") +
    ylim(0,22000) +
    annotate(geom="text", x=as.Date("2017-01-01"), y=20089, 
             label="Bitcoin price reached 20k $\nat the end of 2017") +
    annotate(geom="point", x=as.Date("2017-12-17"), y=20089, size=10, shape=21, fill="transparent")

→ Abline


Q1.4 - Add a horizontal abline to show what part of the curve is over 5000 $. This is possible thanks to the geom_hline() function that requires its yintercept argument.

# Find spike date and value:
# data %>% arrange(desc(value)) %>% head(1)

# plot
data %>% 
  ggplot( aes(x=date, y=value)) +
    geom_line(color="#69b3a2") +
    ylim(0,22000) +
    annotate(geom="text", x=as.Date("2017-01-01"), y=20089, 
             label="Bitcoin price reached 20k $\nat the end of 2017") +
    annotate(geom="point", x=as.Date("2017-12-17"), y=20089, size=10, shape=21, fill="transparent") +
    geom_hline(yintercept=5000, color="orange", size=.5)

→ Color


Q1.5 - Build a scatterplot based on the gapminder dataset. Use gdpPercap for the X axis, lifeExp for the Y axis, and pop for bubble size. Keep only the year 2007.

# Data are available in the gapminder package
library(gapminder)
data <- gapminder %>% filter(year=="2007") %>% select(-year)

# Basic scatterplot
ggplot( data, aes(x=gdpPercap, y=lifeExp, size = pop, color = continent)) +
    geom_point(alpha=0.7) 


Q1.6 - Highlight South Africa in the chart: draw it in red, with all other circles in grey. Follow those steps:

  • create a new column with mutate: this new column has the value yes if country=="South Africa", no otherwise. This is possible thanks to the ??felse function.
  • in the aesthetics part of the ggplot call, use this new column to control dot colors
  • use
# Basic scatterplot
data %>%
  mutate(isSouthAfrica = ifelse(country=="South Africa", "yes", "no")) %>%
  ggplot( aes(x=gdpPercap, y=lifeExp, size = pop, color = isSouthAfrica)) +
    geom_point(alpha=0.7) +
    scale_color_manual(values=c("grey", "red")) +
    theme(legend.position="none")

→ Multiple text


Q1.7 - Highlight every country with gdpPercap > 5000 & lifeExp < 60 in red. Write their names using the geom_text_repel of the ggrepel package

# ggrepel
library(ggrepel)

# prepare data
tmp <- data %>%
  mutate( annotation = ifelse(gdpPercap > 5000 & lifeExp < 60, "yes", "no"))

# plot
tmp %>%
  ggplot( aes(x=gdpPercap, y=lifeExp, size = pop, color = continent)) +
    geom_point(alpha=0.7) +
    theme(legend.position="none") +
    geom_text_repel(data=tmp %>% filter(annotation=="yes"), aes(label=country), size=4 )

→ Bonus

Faceting


→ facet_wrap()

# Libraries
library(babynames)

# Load dataset from github
data <- babynames %>% 
  filter(name %in% c("Ashley", "Amanda", "Jessica",    "Patricia", "Linda", "Deborah",   "Dorothy", "Betty", "Helen")) %>%
  filter(sex=="F")

# line plot = spaghetti chart
data %>%
  ggplot( aes(x=year, y=n, group=name, color=name)) +
    geom_line() +
    ggtitle("Popularity of American names in the previous 30 years")

data %>%
  ggplot( aes(x=year, y=n, group=name, fill=name)) +
    geom_area() +
    ggtitle("Popularity of American names in the previous 30 years") +
    theme(
      legend.position="none",
    ) +
    facet_wrap(~name, scale="free_y")

→ facet_grid()

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/10_OneNumSevCatSubgroupsSevObs.csv", header=T, sep=",")

# Plot
ggplot(data, aes(x=total_bill)) +
  geom_histogram() +
  facet_grid(sex~day)

Saving plots


Colors


6- Interactive charts


An interactive chart is a chart on which you can zoom, hover shapes to get tooltips, click to trigger actions and more. Building interactive charts requires javascript under the hood, but it is relatively easy to build it using R packages that wrap the javascript for you. This type of packages are called HTML widgets.

Plotly


Q6.1 - Build the gapminder bubble plot you’ve already done in the annotation part of this practical. Store it in an object called p

# load data
library(gapminder)
data <- gapminder %>% filter(year=="2007") %>% select(-year)

# Basic ggplot
p <- data %>%
  ggplot( aes(x=gdpPercap, y=lifeExp, size = pop, color = continent)) +
    geom_point(alpha=0.7) 
p


Q6.2 - Install and load the plotly package. Build an interactive chart using the ggplotly() function. What are the new functionalities of this chart? Is it useful? What could be better?

# Interactive version
library(plotly)
ggplotly(p)


Q6.3 - Let’s improve the tooltip of the chart:

  • build a new column called myText. Fill it with whatever you want to show in the tooltip.
  • add a new aesthetics: text=myText
  • in the ggplotly() call, add tooltip="text"
# Basic ggplot
p <- data %>%
  mutate(myText=paste("This country is: " , country )) %>%
  ggplot( aes(x=gdpPercap, y=lifeExp, size = pop, color = continent, text=myText)) +
    geom_point(alpha=0.7) 

ggplotly(p, tooltip="text")

HTML widgets

 




A work by a practical by Yan Holtz

yan.holtz.data@gmail.com